//
// Created by huayang on 17-8-14.
//

#ifndef FIGHTER_TDSS_H
#define FIGHTER_TDSS_H

#include <iostream>
#include <map>
#include <sys/mman.h>

const int kEmpty = 0;
const int kUsed  = 1;

enum TdssErrCode {
  kOk,
  kFailed  = -1,
  kErrFull = -2,
};

const int kIdCnt        = 16;
const int kSections     = 1 << 2;
const int kEachSections = 1 << 1;
const int kEachSegments = 1 << 1;

struct Header {
  char magic[4];
  char version[4];
  int section_offsets[kSections];
};

struct SectionNode {
  int segments_offset;
  int state;
};

struct Sections {
  SectionNode sections[kEachSections];
};

struct SegmentNode {
  int type;
  char id[kIdCnt];
  int offset;
  int state;
  unsigned int total_length;
  unsigned int name_length;
};

struct Segments {
  SegmentNode segments[kEachSegments];
};

struct BaseData {
  SegmentNode segment;
  const char* data;
};

class Tdss {
public:
  Tdss();
  ~Tdss();

  //Create File
  int CreateTdssFile(const char* name, size_t cache_size);

  //Map file
  void* MapTdssFile(int fd, size_t len, size_t offset);

  //Ummap
  void Umap();

  //Init
  TdssErrCode Init(const char* name, size_t size, std::string magic, std::string version);

  //Release
  void Release();

  //Add SectionNode item
  int AddSegmentItem(const SegmentNode& segment);

  //Return empty SegmentNode index
  int FindEmptySegment();

  //Add Data
  int AddData(BaseData& data);

  //Gen new Segments
  int GenSegments();

  //Gen new Sections
  int GenSections();

  //Index of Sections in header
  int FindEmptySectionsInHeader();

  //Return empty section index
  int FindEmptySection();

private:
  Header* ParseHeader(void* addr);
  Sections* ParseSections(void* addr);
  Segments* ParseSegments(void* addr);

  //Addr start
  void* start_;
  //Offset from addr
  int global_pos_;
  //File size
  size_t cache_size_;
  int fd_;

  Header* header_;
  Sections* curr_sections_;
  Segments* curr_segments_;
};

#endif //FIGHTER_TDSS_H
